package com.aotain.oframework.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.aotain.oframework.constant.DateFormatConstant;
import com.aotain.oframework.util.date.DateUtils;

/**
 * 1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为：7－9－10－5－8－4－2－1－6－3－7－9－10－5－8－4－2。
 * 2、将这17位数字和系数相乘的结果相加。
 * 3、用加出来和除以11，看余数是多少？
 * 4、余数只可能有0－1－2－3－4－5－6－7－8－9－10这11个数字。其分别对应的最后一位身份证的号码为1－0－X －9－8－7－6－5－4－3－2。
 * 5、通过上面得知如果余数是2，就会在身份证的第18位数字上出现的是 X 。如果余数是10，身份证的最后一位号码就是罗马数字 2 。
 * @author Jacob.cw.Zhang@gmail.com
 */
public class IDCardValidate {
	
	private static Log log = LogFactory.getLog(IDCardValidate.class);
	private static String[] modulusArray = {"7","9","10","5","8","4","2","1","6","3","7","9","10","5","8","4","2"};
	private static String[] verifyCodeArray = {"1","0","X","9","8","7","6","5","4","3","2"};
	private static String errorInfo = "";
	
	/**
	 * 根据传入的身份证号码，校验其合法性
	 * @param idCardString	身份证号码
	 * @return
	 */
	public static String validate(String idCardString){
		log.info("The id card number is :" + idCardString);
		boolean isValid = validateLength(idCardString);
		if (isValid) {
			isValid = validateBirthday(idCardString);
			if (isValid) {
				isValid = validateCheckNumber(idCardString);
				if (isValid) {
					errorInfo = "";
				} else {
					errorInfo = "It is the illegal identity card number.";
				}
			} else {
				errorInfo = "The birthday of id card is invalid.";
			}
		} else {
			errorInfo = "The length of ID number should be 15 or 18.";
		}
		return errorInfo;
	}

	private static boolean validateCheckNumber(String idCardString) {
		String number = unifyCardNumber(idCardString);
		log.info("The unify card number is :" + number);
		int totalNumber = 0;
		for (int i = 0; i < modulusArray.length; i++) {
			totalNumber += Integer.parseInt(String.valueOf(number.charAt(i))) * Integer.parseInt(modulusArray[i]);
		}
		log.info("The total number is :" + totalNumber);
		int modValue = totalNumber % 11;
		log.info("The remainder is :" + modValue);
		String verifyCode = verifyCodeArray[modValue];
		log.info("The verify code is :" + verifyCode);
		number = number + verifyCode;
		if (idCardString.length() == 18) {
			if (idCardString.equals(number)) {
				return true;
			} else {
				return false;
			}
		}
		return false;
	}

	private static boolean validateBirthday(String idCardString) {
		boolean isValid = validateLength(idCardString);
		String number = "";
		String year = "";
		String month = "";
		String day = "";
		if (isValid) {
			number = unifyCardNumber(idCardString);
			year = number.substring(6, 10);
			month = number.substring(10, 12);
			day = number.substring(12, 14);
			log.info("The year of card number is :" + year + ",month is :" + month + ",day is :" + day);
			isValid = DateUtils.isDate(DateFormatConstant.DATE_WITHOUT_SEPARATOR_LONG, year + month + day);
			if (isValid) {
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	private static String unifyCardNumber(String idCardString) {
		boolean isValid = validateLength(idCardString);
		String number = "";
		if (isValid) {
			if (idCardString.length() == 18) {
				number = idCardString.substring(0, 17);
			} else if (idCardString.length() == 15) {
				number = idCardString.substring(0, 6) + "19" + idCardString.substring(6, 15);
			}
		} 
		return number;
	}

	private static boolean validateLength(String idCardString) {
		if (idCardString == null) {
			return false;
		} else {
			if (idCardString.length() == 15 || idCardString.length() == 18) {
				return true;
			} else {
				return false;
			}
		}
	}

	public static void main(String[] args) {
		System.out.println(IDCardValidate.validate("420821198709136117"));
	}
	
}
